import os
import platform
import re

from ..subprocess_code_interpreter import SubprocessCodeInterpreter


class Shell(SubprocessCodeInterpreter):
    file_extension = 'sh'
    proper_name = 'Shell'

    def __init__(self):
        super().__init__()

        # Determine the start command based on the platform
        if platform.system() == 'Windows':
            self.start_cmd = 'cmd.exe'
        else:
            self.start_cmd = os.environ.get('SHELL', 'bash')

    def preprocess_code(self, code):
        return preprocess_shell(code)

    def line_postprocessor(self, line):
        return line

    def detect_active_line(self, line):
        if '##active_line' in line:
            return int(line.split('##active_line')[1].split('##')[0])
        return None

    def detect_end_of_execution(self, line):
        return '##end_of_execution##' in line


def preprocess_shell(code):
    """
    Add active line markers
    Wrap in a try except (trap in shell)
    Add end of execution marker
    """

    # Add commands that tell us what the active line is
    # if it's multiline, just skip this. soon we should make it work with multiline
    if not has_multiline_commands(code):
        code = add_active_line_prints(code)

    # Add end command (we'll be listening for this so we know when it ends)
    code += '\necho "##end_of_execution##"'

    return code


def add_active_line_prints(code):
    """
    Add echo statements indicating line numbers to a shell string.
    """
    lines = code.split('\n')
    for index, line in enumerate(lines):
        # Insert the echo command before the actual line
        lines[index] = f'echo "##active_line{index + 1}##"\n{line}'
    return '\n'.join(lines)


def has_multiline_commands(script_text):
    # Patterns that indicate a line continues
    continuation_patterns = [
        r'\\$',  # Line continuation character at the end of the line
        r'\|$',  # Pipe character at the end of the line indicating a pipeline continuation
        r'&&\s*$',  # Logical AND at the end of the line
        r'\|\|\s*$',  # Logical OR at the end of the line
        r'<\($',  # Start of process substitution
        r'\($',  # Start of subshell
        r'{\s*$',  # Start of a block
        r'\bif\b',  # Start of an if statement
        r'\bwhile\b',  # Start of a while loop
        r'\bfor\b',  # Start of a for loop
        r'do\s*$',  # 'do' keyword for loops
        r'then\s*$',  # 'then' keyword for if statements
    ]

    # Check each line for multiline patterns
    for line in script_text.splitlines():
        if any(
                re.search(pattern, line.rstrip())
                for pattern in continuation_patterns):
            return True

    return False
